Skip to content

fix(ledger): honor feature-restricted balance sources - #4609

Merged
GAlexIHU merged 2 commits into
mainfrom
fix/feature-restricted-balances
Jun 30, 2026
Merged

fix(ledger): honor feature-restricted balance sources#4609
GAlexIHU merged 2 commits into
mainfrom
fix/feature-restricted-balances

Conversation

@GAlexIHU

@GAlexIHU GAlexIHU commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • apply live customer-balance impacts against route-level eligible credit sources instead of aggregate settled balance
  • prevent breakage-backed sources from bypassing feature eligibility
  • add regression coverage for feature-restricted live balances and breakage source filtering

Tests

  • nix develop --impure .#ci -c env POSTGRES_HOST=127.0.0.1 go test -tags=dynamic ./openmeter/ledger/customerbalance
  • nix develop --impure .#ci -c env POSTGRES_HOST=127.0.0.1 go vet -tags=dynamic ./openmeter/ledger/customerbalance
  • nix develop --impure .#ci -c env POSTGRES_HOST=127.0.0.1 go test -tags=dynamic ./openmeter/ledger/collector
  • nix develop --impure .#ci -c env POSTGRES_HOST=127.0.0.1 go vet -tags=dynamic ./openmeter/ledger/collector
  • git diff --check

Summary by CodeRabbit

  • Bug Fixes
    • Live balance calculations now correctly enforce feature eligibility, ensuring restricted credits and bounded usage impacts only apply when the feature matches.
    • Breakage-related entries are filtered consistently by feature eligibility, preventing unrelated breakage from affecting customer balances.
    • Live balance is now computed from ordered balance sources to ensure accurate consumption/matching behavior.
  • Tests
    • Added coverage for feature-filtered breakage collection and for bounded usage impacts not applying to ineligible restricted credits.

@GAlexIHU
GAlexIHU requested a review from a team as a code owner June 30, 2026 10:23
@GAlexIHU GAlexIHU added the release-note/ignore Ignore this change when generating release notes label Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1dc919ad-d16b-4ba2-859b-74e1234e395f

📥 Commits

Reviewing files that changed from the base of the PR and between be65b37 and b67b405.

📒 Files selected for processing (1)
  • openmeter/ledger/customerbalance/calculation.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • openmeter/ledger/customerbalance/calculation.go

📝 Walkthrough

Walkthrough

Adds feature-key filtering to breakage-plan FBO collection and refactors live balance calculation to consume impacts against feature-matched sub-account sources. CalculateLiveBalanceFromSources replaces CalculateLiveBalance, with supporting source collection, helpers, and tests.

Changes

Feature-key eligibility filtering for FBO and live balance

Layer / File(s) Summary
Breakage FBO feature-key filtering
openmeter/ledger/collector/collection_fbo.go, openmeter/ledger/collector/collection_fbo_test.go
Breakage-plan loop now skips plans whose route.Features is non-empty and does not include the requested featureKey. The integration test checks restricted and unrestricted breakage selection.
Live balance calculation with feature-matched sources
openmeter/ledger/customerbalance/calculation.go
Adds Impact.FeatureKey(), replaces CalculateLiveBalance with CalculateLiveBalanceFromSources, and adds helpers to match and consume live-balance sources by feature key.
GetBalance source wiring
openmeter/ledger/customerbalance/service.go, openmeter/ledger/customerbalance/service_test.go
GetBalance now builds ordered liveBalanceSource entries from sub-account balances and passes them into CalculateLiveBalanceFromSources. The regression test covers bounded usage impacts against restricted credits.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • turip
  • tothandras

Suggested labels

release-note/bug-fix, area/billing

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: ledger balance handling now honors feature-restricted sources.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/feature-restricted-balances

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes balance handling for feature-restricted ledger credits. The main changes are:

  • Applies live charge impacts against eligible credit sources.
  • Filters breakage-backed sources by feature eligibility.
  • Adds tests for restricted live balances and breakage source filtering.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
openmeter/ledger/customerbalance/calculation.go Adds source-aware live balance consumption with feature eligibility checks.
openmeter/ledger/customerbalance/service.go Builds ordered live balance sources and uses them for live balance calculation.
openmeter/ledger/collector/collection_fbo.go Filters breakage-backed FBO collection sources by route feature eligibility.
openmeter/ledger/customerbalance/service_test.go Adds tests for restricted credits that are not eligible for a live usage charge.
openmeter/ledger/collector/collection_fbo_test.go Adds tests for breakage-backed source filtering by feature.

Reviews (2): Last reviewed commit: "fix(ledger): order customer balance impo..." | Re-trigger Greptile

@GAlexIHU
GAlexIHU enabled auto-merge (squash) June 30, 2026 10:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
openmeter/ledger/collector/collection_fbo.go (1)

207-208: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer slices.Contains for this new membership check.

Tiny cleanup: this is a plain slice lookup, so the standard helper fits better than lo.Contains. If you touch it, it’d be nice to align the nearby identical check too. As per coding guidelines, “Prefer standard library slices and maps helpers for common collection operations.”

♻️ Proposed direction
-		if len(route.Features) > 0 && !lo.Contains(route.Features, featureKey) {
+		if len(route.Features) > 0 && !slices.Contains(route.Features, featureKey) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/ledger/collector/collection_fbo.go` around lines 207 - 208, The
feature membership check in collection_fbo.go currently uses lo.Contains for a
plain slice lookup; switch this and the nearby identical route.Features check in
the same collection logic to the standard library slices.Contains helper. Update
the relevant condition(s) in the collector flow so the membership tests are
consistent with the coding guideline and no longer rely on lo.Contains.

Source: Coding guidelines

openmeter/ledger/customerbalance/service.go (1)

336-345: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Watch the new N+1 balance-query path.

This now calls GetSubAccountBalance once per matching sub-account during GetBalance. For customers with many feature/priority routes, that can turn a balance read into many DB-backed balance reads; a batched “balances by sub-account/route” query would keep the new allocability behavior without the round-trip growth. As per path instructions, “Anything related to event ingestion, message processing, database operations should be vetted for potential performance bottlenecks.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/ledger/customerbalance/service.go` around lines 336 - 345, The new
GetBalance loop introduces an N+1 database pattern by calling
GetSubAccountBalance once per matching sub-account in the subAccounts iteration.
Update the GetBalance flow in customerbalance/service.go to batch these lookups
through a single balances-by-sub-account/route query in BalanceQuerier, then map
results back to each subAccount while preserving the existing routeFilter and
allocability behavior. Use the GetBalance and GetSubAccountBalance paths to
locate the change and replace the per-item DB round trips with one batched
fetch.

Source: Path instructions

openmeter/ledger/collector/collection_fbo_test.go (1)

143-158: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the repo’s decimal assertion style here.

These expected values are simple integers, so require.Equal(..., Amount.InexactFloat64()) matches the test guideline and keeps failures a bit cleaner. As per coding guidelines, “When asserting alpacadecimal.Decimal equality in tests, prefer require.Equal(t, expectedFloat64, actual.InexactFloat64()) and simple float64(...) literals when precision allows.”

♻️ Proposed test assertion cleanup
-	require.True(t, alpacadecimal.NewFromInt(30).Equal(sources[0].Amount), "restricted source amount: %s", sources[0].Amount)
+	require.Equal(t, float64(30), sources[0].Amount.InexactFloat64(), "restricted source amount")
 	require.Empty(t, sources[1].Address.Route().Route().Features)
-	require.True(t, alpacadecimal.NewFromInt(10).Equal(sources[1].Amount), "unrestricted source amount: %s", sources[1].Amount)
+	require.Equal(t, float64(10), sources[1].Amount.InexactFloat64(), "unrestricted source amount")
@@
-	require.True(t, alpacadecimal.NewFromInt(10).Equal(unattributedSources[0].Amount), "unrestricted source amount: %s", unattributedSources[0].Amount)
+	require.Equal(t, float64(10), unattributedSources[0].Amount.InexactFloat64(), "unrestricted source amount")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/ledger/collector/collection_fbo_test.go` around lines 143 - 158,
The test assertions in collectCustomerFBOForFeatureForTest are using
alpacadecimal equality directly for simple integer expectations, but the repo
prefers decimal assertions via float64 comparisons in tests. Update the checks
on the Amount values in collection_fbo_test.go to use require.Equal with
expected float64 literals against Amount.InexactFloat64(), including the
sources[0], sources[1], and unattributedSources[0] assertions, while keeping the
surrounding feature/length checks unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@openmeter/ledger/collector/collection_fbo_test.go`:
- Around line 143-158: The test assertions in
collectCustomerFBOForFeatureForTest are using alpacadecimal equality directly
for simple integer expectations, but the repo prefers decimal assertions via
float64 comparisons in tests. Update the checks on the Amount values in
collection_fbo_test.go to use require.Equal with expected float64 literals
against Amount.InexactFloat64(), including the sources[0], sources[1], and
unattributedSources[0] assertions, while keeping the surrounding feature/length
checks unchanged.

In `@openmeter/ledger/collector/collection_fbo.go`:
- Around line 207-208: The feature membership check in collection_fbo.go
currently uses lo.Contains for a plain slice lookup; switch this and the nearby
identical route.Features check in the same collection logic to the standard
library slices.Contains helper. Update the relevant condition(s) in the
collector flow so the membership tests are consistent with the coding guideline
and no longer rely on lo.Contains.

In `@openmeter/ledger/customerbalance/service.go`:
- Around line 336-345: The new GetBalance loop introduces an N+1 database
pattern by calling GetSubAccountBalance once per matching sub-account in the
subAccounts iteration. Update the GetBalance flow in customerbalance/service.go
to batch these lookups through a single balances-by-sub-account/route query in
BalanceQuerier, then map results back to each subAccount while preserving the
existing routeFilter and allocability behavior. Use the GetBalance and
GetSubAccountBalance paths to locate the change and replace the per-item DB
round trips with one batched fetch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e09e6d43-2d06-4033-ae47-0838f1da0938

📥 Commits

Reviewing files that changed from the base of the PR and between 60126ca and be65b37.

📒 Files selected for processing (5)
  • openmeter/ledger/collector/collection_fbo.go
  • openmeter/ledger/collector/collection_fbo_test.go
  • openmeter/ledger/customerbalance/calculation.go
  • openmeter/ledger/customerbalance/service.go
  • openmeter/ledger/customerbalance/service_test.go

@GAlexIHU
GAlexIHU merged commit d04b21d into main Jun 30, 2026
26 checks passed
@GAlexIHU
GAlexIHU deleted the fix/feature-restricted-balances branch June 30, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/ignore Ignore this change when generating release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants